#******************************************************************************
#Copyright (c) 2013-2014, Altera Corporation.  All rights reserved.
#
#Redistribution and use of this software, in source and binary code forms, with or without modification, are permitted provided that the following conditions are met:
#
#1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
#
#2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
#
#3. Neither the name of Altera Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT HOLDERS OR CONTRIBUTORS ARE ADVISED OF THE POSSIBILITY DAMAGE IS LIKELY TO OCCUR.
#******************************************************************************/

### config.mk -> The place to put configuration so that you don't
###              have to pass it on the command line every time
include config.mk

export all

###### Device specific variables

ifeq ($(DEVICE), arria10)
 SOC_DEFS := -Dsoc_a10
 SOC := soc_a10
 U_BOOT := u-boot.axf
else
 SOC := soc_cv_av
 U_BOOT := u-boot-spl.axf
 ifeq ($(DEVICE), cyclone5)
  SOC_DEFS := -DCYCLONE5 -Dsoc_cv_av
 else
  SOC_DEFS := -DARRIA5 -Dsoc_cv_av
 endif
endif

SHELL := /bin/bash

ifeq ($(VERBOSE),)
SIL=@
endif

###### Directories, etc
CP       ?= cp
SRC_DIR  ?= src/sparrow
QCOM_DIR ?= src/qcom
GEN_DIR  ?= gen/$(PROJ)
PROJ_DIR ?= src/$(PROJ)
OBJ_DIR  ?= objs/$(PROJ)_$(DEVICE)
BIN      ?= $(DEVICE)
BIN_DIR  ?= $(DEVICE)/$(PROJ)
LINUX_OBJ_DIR := $(OBJ_DIR).linux
HWLIB_DIR ?= $(SOCEDS_DEST_ROOT)/ip/altera/hps/altera_hps/hwlib
HWLIB_SRC ?= $(HWLIB_DIR)/src/hwmgr
SOC_SRC   ?= $(HWLIB_SRC)/$(SOC)
UTILS_SRC ?= $(HWLIB_DIR)/src/utils

INCLUDE_DIRS = -I $(SRC_DIR) -I $(QCOM_DIR) -I $(HWLIB_DIR)/include -I $(HWLIB_DIR)/include/$(SOC) -I $(GEN_DIR) $(EXTRA_INCLUDES)

### VPATH is similar to an include path, but for source files
ifeq ($(PROJ),)
 VPATH := $(HWLIB_SRC):$(SOC_SRC):$(UTILS_SRC):$(SRC_DIR)
else
 VPATH := $(HWLIB_SRC):$(SOC_SRC):$(UTILS_SRC):$(SRC_DIR):$(GEN_DIR):$(PROJ_DIR)
endif

COMPILER ?= GNU

####### Makefile functions
### src_2_obj(object_dir, sources) - returns the object files for given sources
define src_2_obj
  $(addsuffix .o,$(addprefix $(1)/,$(notdir $(basename $(2)))))
endef


ifeq ($(COMPILER), GNU)
  # Use the GNU compiler
  CROSS_COMPILE ?= arm-altera-eabi-

  CC=$(CROSS_COMPILE)gcc
  CFLAGS_COMPILER =-march=armv7-a -mtune=cortex-a9 -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=hard -marm -std=c99 -fno-builtin -DGNU

  AS=$(CROSS_COMPILE)gcc
  ASFLAGS_COMPILER:= -c $(CFLAGS_COMPILER)

  LD=$(CROSS_COMPILE)gcc
  LDFLAGS_COMPILER:=-nostdlib -Wl,-N,--build-id=none
  LD_SET_ADDRESS=-Wl,-Ttext=
  #-Wl,-e_start 

  MKDIR    ?=$(SIL)mkdir -p

  OBJ_DUMP ?=$(CROSS_COMPILE)objdump 
  OBJ_DUMP_OPTS=-DS

  OBJ_COPY ?=$(CROSS_COMPILE)objcopy
  OBJ_COPY_OPTS = -O binary #Note- This must end with a space

  alt_interrupt_srcs := \
	$(HWLIB_SRC)/alt_interrupt.c

else
  # Use the ARM compiler
  AS=armasm
  ASFLAGS_COMPILER:=-g --cpu=Cortex-A9 --cpreproc

  CC=armcc
  #warning 370-D: variable "" has an uninitialized const field: Caused by socal generated .h files
  CFLAGS_COMPILER	:= --cpu=Cortex-A9 --diag_suppress 370 --library_interface=aeabi_clib --c99 -DARMCC

  LD=armlink
  #warning 6238 - warns of aligning stack properly when calling C code from asm
  LDFLAGS_COMPILER:=--entry=_start --first=_start --diag_suppress 6238 --noscanlib
  LD_SET_ADDRESS=--ro-base 
  MKDIR    ?=$(SIL)mkdir -p

  OBJ_DUMP ?=fromelf
  OBJ_DUMP_OPTS=--text -c -s -d 

  OBJ_COPY ?=fromelf
  OBJ_COPY_OPTS = --bin --output=

  alt_interrupt_srcs := \
	$(HWLIB_SRC)/alt_interrupt.c \
	$(HWLIB_SRC)/alt_interrupt_armcc.s
    
endif

###### Python information
PYTHON   ?=python
PYOPTS   ?=-D $(DEVICE)
ifdef SYSTEMROOT
	MKIMAGE  ?=mkimage.exe
else
	MKIMAGE  ?=PATH=$(PATH):prebuilt mkimage
endif

PYSCRIPT ?= $(SRC_DIR)/Sparrow.py
PROJSCRIPT ?= $(PROJ_DIR)/layout.py
GEN_DEPS ?= $(GEN_DIR) $(PY_FILES) $(PYSCRIPT)

###### Flags
CCFLAGS = $(CFLAGS_COMPILER) -c $(INCLUDE_DIRS) -DARM -g -D$(SOC) -DPRINTF_UART
ASFLAGS = $(ASFLAGS_COMPILER) $(INCLUDE_DIRS)
LDFLAGS = $(LDFLAGS_COMPILER)
CCFLAGS += -DALT_INT_PROVISION_VECTOR_SUPPORT=0
LINUX_CFLAGS = -g -O0 -DLINUX 

.PHONY: all
ifeq ($(PROJ),)
 PROJECTS ?= baremetal linux_baremetal linux_uCos2 baremetal_dual uCos2_uCos2
 all: $(PROJECTS)
 
else
 all: proj_all
 
endif

srcs_hosting := \
    $(SRC_DIR)/mem.c \
    $(SRC_DIR)/divide.c \
    $(UTILS_SRC)/alt_printf.c \
	$(HWLIBS_DIR)/alt_p2uart.c \
	$(HWLIBS_DIR)/alt_16550_uart.c

##########################################################################################################
#		Generic Rules
##########################################################################################################

$(OBJ_DIR)/%.o: %.c $(GEN_DIR)/Layout.h
	$(SIL)$(CC) $(CCFLAGS) -o $@ $<

$(OBJ_DIR)/%.o: %.S $(GEN_DIR)/Layout.h
	$(SIL)$(AS) $(ASFLAGS) -o $@ $<

$(OBJ_DIR) $(GEN_DIR) $(BIN_DIR) $(BIN)/test/local:
	$(SIL)$(MKDIR) $@

clean:
	$(SIL)rm -rf objs cyclone5 arria5 arria10 gen src/Sparrow.pyo

.PHONY: dumpLogScript
dumpLogScript: $(BIN_DIR)/dumpLog.sh

.PHONY: dumpLog
dumpLog: $(LINUX_OBJ_DIR)/dumpLog

### Rules for building sparrow itself

CONFIG_FILE = $(PROJ_DIR)/layout.py
$(BIN_DIR)/sparrow.txt: $(BIN_DIR)/sparrow.axf
	$(SIL)$(OBJ_DUMP) $(OBJ_DUMP_OPTS) $< >$@

$(BIN_DIR)/sparrow.map: $(PROJ_DIR)/layout.py
	$(SIL)$(PYTHON) $(PYSCRIPT) $(PROJSCRIPT) $(PYOPTS) -p >$@

$(BIN_DIR)/bootscript.txt: $(PROJ_DIR)/layout.py
	$(SIL)$(PYTHON) $(PYSCRIPT) $(PROJSCRIPT) $(PYOPTS) -boots $@
	$(SIL)dos2unix -q $@

$(BIN_DIR)/u-boot.scr: $(BIN_DIR)/bootscript.txt
	$(SIL)$(MKIMAGE) -A arm -O linux -T script -C none -a 0 -e 0 -n "bootscript" -d $< $@ > /dev/null

$(GEN_DIR)/Layout.c $(GEN_DIR)/Layout.h: $(GEN_DEPS) $(CONFIG_FILE)
	$(SIL)$(PYTHON) $(PYSCRIPT) $(PROJSCRIPT) $(PYOPTS) -C $(GEN_DIR)/Layout.c -H $(GEN_DIR)/Layout.h	

# Special rule required for Windows to build
$(OBJ_DIR)/Layout.o: $(GEN_DIR)/Layout.c $(GEN_DIR)/Layout.h
	$(SIL)$(CC) $(CCFLAGS) -o $@ $<

$(BIN_DIR)/sparrow.bin: $(BIN_DIR)/sparrow.axf $(CONFIG_FILE)
	$(SIL)$(OBJ_COPY) $< $(OBJ_COPY_OPTS)$(OBJ_DIR)/sparrow.raw  && \
	$(MKIMAGE) -A arm -O linux -T kernel -C none \
		-a `$(PYTHON) $(PYSCRIPT) $(PROJSCRIPT) $(PYOPTS) -var 'sparrow.Executable.Address'` \
		-e `$(PYTHON) $(PYSCRIPT) $(PROJSCRIPT) $(PYOPTS) -var 'sparrow.Executable.Start'` \
		-d $(OBJ_DIR)/sparrow.raw $@ > /dev/null && \
	chmod a+x $@
	@echo "*** Created $@ ***"

###### Rules for samples
%:
		$(SIL)make --no-print-directory -f src/$@/Makefile.inc


.PHONY: help
help:
		@echo You can build one of the samples, or your own project
		@echo To build a sample, make one of the following targets:
		@echo            baremetal, baremetal_dual, linux_baremetal, linux_uCos2 uCos2_uCos2
		@echo To create your own project, you can start by copying one of the samples directories in src/
		@echo           cp src/linux_baremetal src/myproj
		@echo
		@echo To build your own project, put your project in src and compile it using the new directory name:
		@echo            make myproj


